/*
 * Copyright (c) 2008 by 1eEurope (Switzerland) AG, Thalwil
 *
 * Customer:	1eEurope (Switzerland) AG
 * Project:		BKS
 * Created:		30.09.2008, WBL
 *
*/

using By1eEurope.BKS.Tools.Utils;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Navigation;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.Navigation;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace By1eEurope.BKS.Controls
{
    /// <summary>
    /// Intelligent Menu Control. An XML structure of the current site structure is built and rendered with a specified XSLT
    /// </summary>
	[ToolboxData("<{0}:Navigation runat=\"server\" />")]
    public class Navigation : System.Web.UI.WebControls.Menu
	{
		private string _currentNodeKey = String.Empty;
		private string _xsltPath = "/xsltDocs/Navigation.xslt";

        /// <summary>
        /// Path to the XSLT, that receives and tranforms the XML structure to the desired HTML-Output
        /// </summary>
		[Browsable(true)]
		[Category("Config")]
		[DefaultValue("/xsltDocs/Navigation.xslt")]
		[Description("Relative url to xslt file")]
		public string XsltPath
		{
			get { return _xsltPath; }
			set { _xsltPath = (value != "" ? value : _xsltPath); }
		}

		protected override void Render(HtmlTextWriter htmlTextWriter)
		{
			SiteMapDataSource dataSource = this.GetDataSource() as SiteMapDataSource;
			SiteMapProvider provider = dataSource.Provider;
			SiteMapNode currentNode = provider.CurrentNode;

			_currentNodeKey = currentNode.Key.ToString();

			XmlDocument xmlDocument = new XmlDocument();
			XmlNode xmlNodeRoot = AddXmlNode(xmlDocument, xmlDocument, "MenuItems");

			AddXmlAttribute(xmlDocument, xmlNodeRoot, "CurrentKey", _currentNodeKey);
			AddXmlAttribute(xmlDocument, xmlNodeRoot, "CurrentLevel", "-1");
			AddXmlAttribute(xmlDocument, xmlNodeRoot, "Level", "-1");
			AddXmlAttribute(xmlDocument, xmlNodeRoot, "ParentKey", "");

			MenuItemCollection items = this.Items;
			if (items.Count > 0)
			{
				foreach (MenuItem item in items)
				{
					renderMenu(item, xmlDocument, xmlNodeRoot);
				}
			}

            XslCompiledTransform xsltDocument = XmlUtil.GetXsltDocument(SPContext.Current.Web, this.XsltPath);
            XsltArgumentList xsltArgumentList = new XsltArgumentList();
            xsltArgumentList.AddParam("Datetime", "", DateTime.Now.ToLongDateString());
            xsltArgumentList.AddParam("Guid", "", Guid.NewGuid().ToString());
            xsltArgumentList.AddParam("Lang", "", SPContext.Current.Web.Locale.Name);
            StringBuilder stringBuilder = XmlUtil.TransformXslt(xsltDocument, xmlDocument.InnerXml, xsltArgumentList);

			htmlTextWriter.Write(stringBuilder.ToString());
		}

		private void renderMenu(MenuItem item, XmlDocument xmlDocument, XmlNode xmlNode)
		{
			string _ImageUrl = item.ImageUrl;
			string _Target = item.Target;
			string _ToolTip = SPEncode.HtmlDecode(item.ToolTip);

			if (_ToolTip.IndexOf(']') > -1)
			{
				ExtractInfo(ref _ToolTip, ref _Target, "[target:");
				ExtractInfo(ref _ToolTip, ref _ImageUrl, "[img:");
			}

			XmlNode xmlNodeTemp = AddXmlNode(xmlDocument, xmlNode, "MenuItem");

			AddXmlAttribute(xmlDocument, xmlNodeTemp, "ImageUrl", _ImageUrl);
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "Url", item.NavigateUrl);
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "Target", _Target);
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "Title", SPEncode.HtmlDecode(item.Text));
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "ToolTip", _ToolTip);
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "Level", item.Depth.ToString());
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "Selected", item.Selected.ToString());
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "Key", item.DataPath.ToString());
			AddXmlAttribute(xmlDocument, xmlNodeTemp, "ParentKey", "");

			if (item.Parent != null)
			{
				AddXmlAttribute(xmlDocument, xmlNodeTemp, "ParentKey", item.Parent.DataPath.ToString());
			}

			if (item.DataPath.ToString().ToLower() == _currentNodeKey.ToLower())
			{
				AddXmlAttribute(xmlDocument, xmlNodeTemp, "Selected", "True");
				AddXmlAttribute(xmlDocument, xmlDocument.ChildNodes[0], "CurrentLevel", item.Depth.ToString());
			}
			else if (_currentNodeKey.ToLower().Contains(item.DataPath.ToString().ToLower()))
			{
				AddXmlAttribute(xmlDocument, xmlNodeTemp, "Selected", "True");
			}

			if (item.ChildItems.Count > 0)
			{
				XmlNode xmlNodeTempSub = AddXmlNode(xmlDocument, xmlNodeTemp, "MenuItems");

				AddXmlAttribute(xmlDocument, xmlNodeTempSub, "Level", (item.Depth + 1).ToString());
				AddXmlAttribute(xmlDocument, xmlNodeTempSub, "ParentKey", item.DataPath.ToString());

				foreach (MenuItem subItem in item.ChildItems)
				{
					renderMenu(subItem, xmlDocument, xmlNodeTempSub);
				}
			}
		}

		private XmlNode AddXmlNode(XmlDocument xmlDocument, XmlNode xmlNode, String nodeName)
		{
			XmlNode xmlNodeTemp = xmlDocument.CreateElement(nodeName);
			return xmlNode.AppendChild(xmlNodeTemp);
		}

		private void AddXmlAttribute(XmlDocument xmlDocument, XmlNode xmlNode, String attributeName, String attributeValue)
		{
			XmlAttribute xmlAttributeTemp = xmlDocument.CreateAttribute(attributeName);
			xmlAttributeTemp.Value = attributeValue;
			xmlNode.Attributes.Append(xmlAttributeTemp);
		}

		private void ExtractInfo(ref String refToExtract, ref String refToFill, String parameterToExtract)
		{
			int iIndexOf = refToExtract.ToLower().IndexOf(parameterToExtract.ToLower());
			if (iIndexOf > -1)
			{
				String temp = String.Empty;

				temp = refToExtract.Substring(refToExtract.IndexOf('[', iIndexOf), refToExtract.IndexOf(']', iIndexOf) + 1);
				refToExtract = refToExtract.Replace(temp, "");

				temp = temp.Replace("[", "");
				temp = temp.Replace("]", "");

				string[] _Temp = temp.Split(':');
				if (_Temp[1].Length > 0)
				{
					refToFill = _Temp[1];
				}
			}
		}

	}
}
